package com.gton.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @description: 全局异常处理不是基于SpringMVC，基于WebFlux
 * @author: GuoTong
 * @createTime: 2022-10-05 10:50
 * @since JDK 1.8 OR 11
 **/
@Component
@SuppressWarnings("all")
@Order(1)
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalErrorWebExceptionHandler.class);

    private final ObjectMapper objectMapper = new ObjectMapper();
    // 过滤日志Logo
    private final String filterLogo = "/favicon.ico";

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        // 获取上下文
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 获取异常
        String message = ex.getMessage();
        if (!filterLogo.equals(request.getPath())) {
            log.error("[全局异常处理] 异常请求路径:,{};错误原因是->{}", request.getPath(), message);
        }
        HttpStatus status = null;
        if (ex instanceof ResponseStatusException) {
            status = ((ResponseStatusException) ex).getStatus();
        }
        if (status == null) {
            status = HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            try {
                return bufferFactory.wrap(objectMapper.writeValueAsBytes(Resp.error(ex.getMessage())));
            } catch (JsonProcessingException e) {
                log.warn("Error writing response", ex);
                return bufferFactory.wrap(new byte[0]);
            }
        }));
    }

}
